package cn.iocoder.yudao.module.system.service.a_audio_and_video;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharPool;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.system.config.tools.FFmpegTools;
import cn.iocoder.yudao.module.system.controller.admin.a_audio_and_video.vo.AudioRespVO;
import cn.iocoder.yudao.module.system.controller.admin.a_audio_and_video.vo.VideoRespVO;
import cn.iocoder.yudao.module.system.controller.admin.a_pictures.vo.FileBaseVO;
import cn.iocoder.yudao.module.system.factory.FileStorageFactory;
import cn.iocoder.yudao.module.system.service.file_storage.UploadService;
import cn.iocoder.yudao.module.system.util.a_gaojian.FileUtil;
import io.vavr.Tuple2;
import jodd.net.URLDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zyk
 */
@Component
@Slf4j
public class VideoUploadServiceImpl implements UploadService {

    @Value("${file.storage}")
    private String FILE_STORAGE;

    @Value("${file.video.path}")
    private String FILE_VIDEO;

    @Value("${file.video.host}")
    private String VIDEO_HOST;

    @Value("${file.temp}")
    private String temp;

    @Resource
    private FFmpegTools fFmpegTools;

    @Resource
    FileStorageFactory factory;

    @Override
    public boolean accept(String s) {
        return false;
    }

    @Override
    public FileBaseVO upload(MultipartFile file) {
        String fileName = URLDecoder.decode(file.getOriginalFilename(), "UTF-8");
        Long size = file.getSize();
        String ext = FileUtil.getExt(fileName);
        log.info("Video upload name:" + fileName + ",size:" + size);
        check(ext, size);
        VideoRespVO videoRespVO = BeanUtil.copyProperties(factory.get(FILE_STORAGE).storage(file, FILE_VIDEO), VideoRespVO.class);
        videoRespVO.setUrl(VIDEO_HOST + "/" + videoRespVO.getRelativePath());
        return handle(videoRespVO);
    }

    @Override
    public void check(String ext, Long size) {
        String videoFormats = "mp4,m4v,3gp,mpg,flv,f4v,swf,avi,wmv,rmvb,mov,mts,m2t,webm,ogg,mkv";
        String videoMaxSize = "10240MB";
        if (StringUtils.isNotBlank(videoFormats)) {
            if (!Arrays.stream(videoFormats.split(String.valueOf(CharPool.COMMA))).anyMatch(s -> s.equalsIgnoreCase(ext))) {
                throw new ServiceException(new ErrorCode(500, String.format("不支持%s视频格式上传!", ext)));
            }
        } else {
            throw new ServiceException(new ErrorCode(500, "请配置视频上传格式"));
        }
        if (StringUtils.isBlank(videoMaxSize)) {
            videoMaxSize = "10240MB";
        }
        Long maxSize = Long.valueOf(videoMaxSize.replace("MB", "").replace("mb", "").replace("m", ""));
        if (size > maxSize * 1024 * 1024) {
            throw new ServiceException(new ErrorCode(500, String.format("视频大小不能超过%s!", videoMaxSize)));
        }
    }

    @Override
    public VideoRespVO merge(String uuid, int chunkTotal, Long size, String ext) {
        String chunkPath = temp + "/" + uuid;
        File chunkTemp = new File(chunkPath);
        if (!chunkTemp.exists()) {
            throw new ServiceException(500, "系统异常！");
        }
        File[] files = chunkTemp.listFiles();
        if (files.length != chunkTotal) {
            throw new ServiceException(501, "分片未全部上传！");
        }
        List<File> list = Arrays.stream(files).sorted(new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                Integer sort1 = Integer.parseInt(f1.getName().replace(uuid + ".part", ""));
                Integer sort2 = Integer.parseInt(f2.getName().replace(uuid + ".part", ""));
                return sort1 - sort2;
            }
        }).collect(Collectors.toList());

        FileBaseVO fileBaseVO = factory.get(FILE_STORAGE).merge(list, size, ext, FILE_VIDEO);
        //删除临时分片接收目录
        chunkTemp.delete();
        VideoRespVO videoRespVO = BeanUtil.copyProperties(fileBaseVO, VideoRespVO.class);
        return handle(videoRespVO);
    }

    private VideoRespVO handle(VideoRespVO videoRespVO){
        videoRespVO.setUrl(VIDEO_HOST + "/" + videoRespVO.getRelativePath());
        String videoPath = FILE_VIDEO + "/" + videoRespVO.getRelativePath();
        Tuple2<Long,Double> tuple2 = fFmpegTools.readVideo(videoPath);
        videoRespVO.setDuration(tuple2._1);
        videoRespVO.setVideoResolution(fFmpegTools.readVideoResolution(videoPath));
        return videoRespVO;
    }
}
